GoのソースをMacでクロスコンパイルし、CentOS5でCloudWatchのカスタムメトリクスを取得する
はじめに
最近、お気に入りの札幌ランチは炎のランチバイキングの横山です。 以下の記事を参考にCloudWatchのカスタムメトリクスを登録スクリプトをGoで作ったものをMacでビルドを行い、CentOS5で実行するまでの手順をまとめました。
前提
- ビルドするMac
$ sw_vers -productVersion 10.10.2 $ brew --version 0.9.5
- 実行するCentOS5
- IAM Roleなし
- Goをビルドする環境なし
- PutMetricsDataを行う権限あり
$ uname -a Linux ip-xxx-xxx-xxx-xxx 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:34:28 EST 2008 x86_64 x86_64 x86_64 GNU/Linux $ cat /etc/redhat-release CentOS release 5.4 (Final)
今回準備したソース
- putMetricsData.go
package main import ( "fmt" "strings" "flag" "os" "github.com/awslabs/aws-sdk-go/aws" "github.com/awslabs/aws-sdk-go/gen/cloudwatch" ) func main() { var nameSpace, metricName, unit, region, dimensions string var value float64 accessKey := os.Getenv("AWS_ACCESS_KEY_ID") secretKey := os.Getenv("AWS_SECRET_ACCESS_KEY") if accessKey == "" || secretKey == "" { fmt.Println("Error: Undefined AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY") os.Exit(9) } creds := aws.Creds( accessKey, secretKey, "" ) flag.StringVar(&nameSpace, "namespace", "", "") flag.StringVar(&metricName, "metric-name", "", "") flag.StringVar(&unit,"unit", "", "") flag.StringVar(®ion, "region", "", "") flag.StringVar(&dimensions, "dimensions", "", "") flag.Float64Var(&value, "value", 0, "") flag.Parse() if len(dimensions) == 0 { fmt.Println("error: --dimensions value empty!") return } cli := cloudwatch.New(creds, region, nil) dimension_strings := strings.Split(dimensions, ",") dimension_items := make([]cloudwatch.Dimension, len(dimension_strings)) for index, dimension_string := range dimension_strings { var items = strings.SplitN(dimension_string, "=", 2) if len(items) > 1 { dimension_items[index].Name = aws.String(items[0]) dimension_items[index].Value = aws.String(items[1]) } } metricDataParam := &cloudwatch.MetricDatum { Dimensions: dimension_items, MetricName: aws.String(metricName), Unit: aws.String(unit), Value: aws.Double(value), } putMetricDataInput := &cloudwatch.PutMetricDataInput{ MetricData: []cloudwatch.MetricDatum{*metricDataParam}, Namespace: aws.String(nameSpace), } fmt.Println(cli.PutMetricData(putMetricDataInput)) }
- memoryUsage.sh
#!/bin/bash export AWS_ACCESS_KEY_ID="AKIAxxxxxxxxxxxxxxxx" export AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" program="./putMetricsData" usage=$(free | head -n 3 | tail -n 1 | awk '{a = $3/($3 + $4)*100; print a}') instanceId=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) region=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/.$//') cw_opts="--namespace Classmethod/EC2" cw_opts=${cw_opts}" --metric-name MemoryUtilization" cw_opts=${cw_opts}" --dimensions InstanceId=${instanceId}" cw_opts=${cw_opts}" --unit Percent" cw_opts=${cw_opts}" --region ${region}" cw_opts=${cw_opts}" --value ${usage}" ${program} ${cw_opts}
クロスコンパイルするための準備
すでにgoをインストールしている場合、クロスコンパイルを行おうとすると次の様なエラーが出ると思います。
$ GOOS=linux GOARCH=amd64 go build putMetricsData.go go build runtime: linux/amd64 must be bootstrapped using make.bash
手動でできるかもですが、楽するために一度brewからGoをアンインストールし、 --with-cc-allオプション使ってインストールし直します。
$ brew uninstall go Uninstalling /usr/local/Cellar/go/1.4.1... $ brew install go --with-cc-all ==> Downloading https://storage.googleapis.com/golang/go1.4.1.src.tar.gz ######################################################################## 100.0% ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> ./make.bash --no-clean ==> Caveats As of go 1.2, a valid GOPATH is required to use the `go get` command: http://golang.org/doc/code.html#GOPATH `go vet` and `go doc` are now part of the go.tools sub repo: http://golang.org/doc/go1.2#go_tools_godoc To get `go vet` and `go doc` run: go get golang.org/x/tools/cmd/vet go get golang.org/x/tools/cmd/godoc You may wish to add the GOROOT-based install location to your PATH: export PATH=$PATH:/usr/local/opt/go/libexec/bin ==> Summary 瑳 /usr/local/Cellar/go/1.4.1: 7696 files, 1.5G, built in 19.3 minutes
参考
ビルド
- Mac上
$ GOOS=linux GOARCH=amd64 go build putMetricsData.go $ file putMetricsData putMetricsData: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
実行
scpやFileZillaなどつかってCentOS5にバイナリを持っていきます。
実行し、問題がなければ出力に<nil>が表示されます。(失敗、問題があるとエラーが表示されます)
$ sh memoryUsage.sh <nil>
エラー例
- PutMetricDataを行う権限がない場合
$ sh memoryUsage.sh User: arn:aws:iam::xxxxxxxxxxxx:user/test_putmetrics is not authorized to perform: cloudwatch:PutMetricData
- IAM Roleがない場合
$ sh memoryUsage.sh decoding <?xml version="1.0" encoding="iso-8859-1"?> IAM credentials
まとめ
以上、CentOS5のみですがクロスコンパイルの実行が確認できました。 これにより、監視するインスタンスにGoをインストールせずにバイナリを設置するだけで、Python2.6が入ってなくても、aws-cliが入ってなくてもカスタムメトリクスをCloudWatchに登録することが出来そうです。
また、確認はしてませんがRaspberryPiにGoのビルド環境を導入せずとも、Macでビルド後RaspberryPi側にバイナリだけ持っていけば動くということも出来そうです(未確認)。